package com.superbit.service.match.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.superbit.core.constant.QuoteOrderConstant;
import com.superbit.core.constant.TradeLogConstants;
import com.superbit.core.entry.CoinTradeBusiType;
import com.superbit.core.entry.QuoteOrder;
import com.superbit.core.entry.UserPayMethod;
import com.superbit.core.entry.UserSafeInfo;
import com.superbit.core.entry.UserTradeRecord;
import com.superbit.core.entry.tradelog.TradeLog;
import com.superbit.core.exception.BusinessException;
import com.superbit.core.exception.ParamInvalidException;
import com.superbit.core.service.QuoteOrderService;
import com.superbit.core.service.TradeLogProxy;
import com.superbit.core.service.TradeLogService;
import com.superbit.core.service.UserAssetService;
import com.superbit.core.service.UserBaseInfoProxy;
import com.superbit.core.service.UserPayMethodProxy;
import com.superbit.core.service.UserSafeInfoProxy;
import com.superbit.core.tools.PageListRes;
import com.superbit.core.vo.QuoteOrderVO;
import com.superbit.service.match.daodefine.CoinTradeBusiTypeDao;
import com.superbit.service.match.daodefine.QuoteOrderDao;
import com.superbit.service.match.daodefine.UserTradeRecordDao;
/**
 * 报价单 相关业务层
 * @author 赵世栋
 * @date 2018-01-08
 *
 */
@Service(value = "quoteOrderService")
public class QuoteOrderServiceImpl implements QuoteOrderService {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private QuoteOrderDao quoteOrderDao;
	@Autowired
	private CoinTradeBusiTypeDao coinTradeBusiTypeDao;
	@Autowired
	private UserAssetService userAssetService;
	@Autowired
	private UserBaseInfoProxy userBaseInfoProxy;
	@Autowired
	private UserPayMethodProxy userPayMethodProxy;
	@Autowired
	private UserSafeInfoProxy userSafeInfoProxy;
	@Autowired
	private UserTradeRecordDao userTradeRecordDao;
	@Autowired
	private TradeLogProxy tradeLogProxy;
	@Autowired
	private TradeLogService tradeLogService;
	
	
	
	
	@Transactional
	@Override
	public boolean buyinQuoteOrder(BigDecimal indexprice,double priceCNY,BigDecimal amountCoin,BigDecimal totalPrice,int ALOtransaction,
			String payType,String coinCode,int buyserUserId,String sellerUserId,long quoteId,int isAutoSetting,String setValue) throws BusinessException {
		logger.info("下买单方法调用:单价，币数量，总价，最小交易值，支付方式，币种,买家id,卖家id,参数:"+Arrays.asList(new Object[]{priceCNY,amountCoin,totalPrice,ALOtransaction,
				payType,coinCode,buyserUserId,sellerUserId}));
		boolean flag =false;
		String refund = null;  //退回余币数 
		boolean isrefund = false;//是否退回剩余币数
		String coinName = checkQuoteOrderCondition(coinCode,buyserUserId);
		if(coinName == null){
			throw new BusinessException("QO0017", "order condition is wrong", null);
		}
		//7、是否有剩余未支付的报价单  包含 0：未付款 就是有没有支付的
		List<TradeLog> tradeLogListByUserId = tradeLogProxy.getBuyTradeLogListByUserId(buyserUserId);
		List<Integer> list =new ArrayList<Integer>();
		for (TradeLog tradeLog : tradeLogListByUserId) {
			list.add(tradeLog.getPayStatus());
		}
		if(list.contains(0)){
		throw new BusinessException("QO019", "please finish your order", null);
		}
		//TODO 买入方的输入金额大于账户剩余的金额
		//买入金额小于卖方的最小金额
		//卖方的余额小于输入价
		//买入时付的款大于报价单剩余的钱
		//下单之前需要冻结用户的资产
		
		priceCNY =new BigDecimal(priceCNY+"").setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_EVEN).doubleValue();
	if(StringUtils.isEmpty(sellerUserId)){
		//检查单价是否合理
		if(!checkPriceIsValid(priceCNY, coinCode, 0)){
			throw new BusinessException("QO001","price unreasonable", null);
		}
		//TODO 判断支付方式是否匹配   //0 银行卡，1 支付宝，2 微信
		List<UserPayMethod> userPayMethods= this.userPayMethodProxy.getUserPayMethodByUserId(Integer.valueOf(buyserUserId+""));
		if(userPayMethods == null || userPayMethods.size() == 0){
				throw new BusinessException("QO007", "binding payment method", null);
		}
		List<String> payList = new ArrayList<String>();
		for (UserPayMethod userPayMethod : userPayMethods) {
				int chanelID = userPayMethod.getChanelID();
				payList.add(String.valueOf(chanelID));
		}
		String[] split = payType.split(",");
			for (String string : split) {
				flag = payList.contains(string);
		}
		if(flag == false){
				throw new BusinessException("QO008", "payment method not match ", null);
		}
		QuoteOrder quoteOrder = new QuoteOrder();
		//是否设置了自动涨幅
		if(isAutoSetting == QuoteOrderConstant.QUOTE_ORDER_YES_SETAUTO){
				//TODO 校验指数价是否符合百分比
			int compareTo = new BigDecimal(priceCNY).compareTo(indexprice.multiply(new BigDecimal(setValue)));
			if(compareTo != 0 ){
				throw new BusinessException("QO023", "settingValue  is wrong", null);
			}
		}
			//挂单开始
			//冻结1000CNY对应的保证金
			quoteOrder.setDealAmount(BigDecimal.ZERO);
			quoteOrder.setFreezeAmount(BigDecimal.ZERO);
			quoteOrder.setALOtransaction(ALOtransaction);
			quoteOrder.setAmountCoin(amountCoin);
			quoteOrder.setCoinCode(coinCode);
			quoteOrder.setCreateTime(new Date());
			quoteOrder.setIsAutoSet(isAutoSetting);
			quoteOrder.setPayType(payType);
			quoteOrder.setPriceCNY(new BigDecimal(priceCNY));
			quoteOrder.setQuoteStatus(QuoteOrderConstant.QUOTE_STATUS_NODEAL);
			quoteOrder.setQuoteType(QuoteOrderConstant.DIRECTION_BUY);
			quoteOrder.setRemainPrice(totalPrice);
			quoteOrder.setSetValue(setValue);
			quoteOrder.setTotalPrice(totalPrice);
			quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_NO);
			quoteOrder.setTradeFee(new BigDecimal(QuoteOrderConstant.QUOTE_TRADE_FEE));
			quoteOrder.setUserId(buyserUserId);
			long id = this.quoteOrderDao.saveQuoteOrder(quoteOrder);
		if(id > 0){
			return true;
			//TODO 优化
		}else{
			return false;
		}
		}else if(quoteId > 0){
			logger.info("指定卖家买入报价单，报价单id,买入用户id,卖出用户id,数量,参数"+Arrays.asList(new Object[]{quoteId,buyserUserId,sellerUserId,amountCoin}));
			//
			QuoteOrder quoteOrder = this.quoteOrderDao.getQuoteOrderInfo(quoteId);
		    //有指定卖家买入
		    UserSafeInfo seller = userSafeInfoProxy.verificationSafeInfo(Integer.valueOf(sellerUserId));
		   if(seller == null ){
			throw new BusinessException("QO014", "seller is not exist ", null);
		   }
		 //买家不能买自己的卖单
		   if(quoteOrder.getUserId() == buyserUserId){
				throw new ParamInvalidException("sellerName", "buyser and seller is same");
			}
		   if(quoteOrder.getUserId() != Integer.valueOf(sellerUserId)){
			   throw new BusinessException("QO016", "seller info is wrong", null);
		   }
		   //买家不能买自己的卖单
		   if(quoteOrder.getUserId() == buyserUserId){
			   throw new BusinessException("QO024", "buyser seller is same ", null); 
		   }
		   BigDecimal  remainAmount = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount());
		   //剩余的币数小于订单数
		   int result = amountCoin.compareTo(remainAmount);
		   if( result == 1){
			   throw new BusinessException("QO021", "order balance is not enought", null);
		   }
		   //如果买入额和卖出额相同就为全部吃货 需要删除对应的报价单产生交易记录
		   if(result == 0){
			   //TODO 全部买入 设置tradeSatus 为最后一笔交易 
			   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_LAST);
			   //TODO 剩余数量是否足够
			   quoteOrder.setDealAmount(quoteOrder.getDealAmount().add(amountCoin));//TODO 已交易数量  交易后数量必须大于最小交易数量否则资产回归
		   }else if(result == -1){
		      //部分买入
			   quoteOrder.setDealAmount(quoteOrder.getDealAmount().add(amountCoin));
			   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_DOING);
		     //TODO 剩余额 100 最小交易额 10 买入 99
			   BigDecimal remainA = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount());//剩余币数量
			   BigDecimal minALO = new BigDecimal(quoteOrder.getALOtransaction());//最小交易金额
			 //TODO 出现质数的处理办法   全局统一是用 TODO ****
			   BigDecimal unit = minALO.divide(quoteOrder.getPriceCNY(),QuoteOrderConstant.QUOTE_CNY_ACCURAY,BigDecimal.ROUND_HALF_EVEN);//TODO 封装
			   //判断剩余数量是否小于最小交易数
			   if(remainA.compareTo(unit) == -1){
				   //余额小于最小交易
				   //1、余额进行退回 2、添加交易记录 3、修改交易状态为2
				   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_LAST);
				   //余额回退
				   isrefund = true;
				   refund = remainA.toString();
			   }else{
				   //余额数可以进行再次交易
				   //1、添加交易记录   2、修改交易状态为1
				   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_DOING);
			   }
		   }
		// 添加交易记录
		//判断报价单余额是否小于最小交易额  币数退回
		this.quoteOrderDao.updateQuoteOrder(quoteOrder);
		TradeLog initTradeLog = tradeLogService.getInitTradeLog();
		initTradeLog.setBuyserUid(buyserUserId);
		initTradeLog.setCoinAmount(amountCoin);
		initTradeLog.setCoinCode(coinCode);
		initTradeLog.setCoinName(coinName);
		initTradeLog.setQuoteId(quoteId);
		initTradeLog.setSellerUid(Integer.valueOf(sellerUserId));
		initTradeLog.setTradeType(TradeLogConstants.TRADE_TYPE_BUY);
		initTradeLog.setUnitPrice(new BigDecimal(priceCNY));
		initTradeLog.setTotalPrice(totalPrice);
		initTradeLog.setPayType(payType);
		initTradeLog.setPoundageBTC(new BigDecimal(QuoteOrderConstant.QUOTE_TRADE_FEE));
		tradeLogService.saveTradeLog(initTradeLog);
		//退回剩余币数
		if(isrefund && refund != null){
			logger.info("报价单余额小于最小交易数量进行退回，报价单号，剩余币数,退回卖家id："+new Object[]{quoteId,refund,sellerUserId});
			userAssetService.freezeUser_Asset(sellerUserId, coinCode, new BigDecimal("-"+refund));
		}
		logger.info("报价订单生成，参数"+Arrays.asList(new Object[]{quoteOrder.toString()}));
		return isrefund;
		}
	return isrefund;
	}


	@Transactional
	@Override
	public boolean selloutQuoteOrder(BigDecimal indexprice,double priceCNY,BigDecimal amountCoin,BigDecimal totalPrice,int ALOtransaction,
			String payType,String coinCode,String buyserUserId,int sellerUserId,long quoteId,int isAutoSetting,String setValue) throws BusinessException {
		logger.info("下卖单方法调用:单价，币数量，总价，最小交易值，支付方式，币种,买家id,卖家id,参数:"+Arrays.asList(new Object[]{priceCNY,amountCoin,totalPrice,ALOtransaction,
				payType,coinCode,buyserUserId,sellerUserId}));
		boolean flag =false;
		String refund = null;  //退回余币数 
		boolean isrefund = false;//是否退回剩余币数
		String coinName = this.checkQuoteOrderCondition(coinCode,sellerUserId);
		if(coinName == null){
			throw new BusinessException("QO0017", "order condition is wrong", null);
		}
		priceCNY =new BigDecimal(priceCNY+"").setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_EVEN).doubleValue();
		//获取对应币种的资产的可用余额 和卖出订单额进行判断
		BigDecimal coinAmouts = this.userAssetService.getCoinAmouts(sellerUserId, coinCode);
		if(amountCoin.compareTo(coinAmouts) == 1){
			throw new BusinessException("QO022", "coin is not enought", null);
		}
		if(StringUtils.isEmpty(buyserUserId)){
			//价格是否在指定范围
			if(!checkPriceIsValid(priceCNY, coinCode, 1)){
				throw new BusinessException("QO001","price unreasonable", null);
			}
			//TODO 判断支付方式是否匹配   //0 银行卡，1 支付宝，2 微信
			List<UserPayMethod> userPayMethods= this.userPayMethodProxy.getUserPayMethodByUserId(sellerUserId);
			if(userPayMethods == null || userPayMethods.size() == 0){
					throw new BusinessException("QO007", "binding payment method", null);
			}
			List<String> payList = new ArrayList<String>();
			for (UserPayMethod userPayMethod : userPayMethods) {
					int chanelID = userPayMethod.getChanelID();
					payList.add(String.valueOf(chanelID));
			}
			String[] split = payType.split(",");
				for (String string : split) {
					flag = payList.contains(string);
			}
			if(flag == false){
					throw new BusinessException("QO008", "payment method not match ", null);
			}
			QuoteOrder sellQuoteOrder = new QuoteOrder();
			//是否设置了自动涨幅
			if(isAutoSetting == QuoteOrderConstant.QUOTE_ORDER_YES_SETAUTO){
					//TODO 校验指数价是否符合百分比
				int compareTo = new BigDecimal(priceCNY).compareTo(indexprice.multiply(new BigDecimal(setValue)));
				if(compareTo != 0 ){
					throw new BusinessException("QO023", "settingValue  is wrong", null);
				}
			}
			//挂单开始
			sellQuoteOrder.setDealAmount(BigDecimal.ZERO);
			sellQuoteOrder.setFreezeAmount(BigDecimal.ZERO);
			sellQuoteOrder.setALOtransaction(ALOtransaction);
			sellQuoteOrder.setAmountCoin(amountCoin);
			sellQuoteOrder.setCoinCode(coinCode);
			sellQuoteOrder.setCreateTime(new Date());
			sellQuoteOrder.setIsAutoSet(isAutoSetting);
			sellQuoteOrder.setPayType(payType);
			sellQuoteOrder.setPriceCNY(new BigDecimal(priceCNY));
			sellQuoteOrder.setQuoteStatus(QuoteOrderConstant.QUOTE_STATUS_NODEAL);
			sellQuoteOrder.setQuoteType(QuoteOrderConstant.DIRECTION_SELL);
			sellQuoteOrder.setRemainPrice(totalPrice);
			sellQuoteOrder.setSetValue(setValue);
			sellQuoteOrder.setTotalPrice(totalPrice);
			sellQuoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_NO);
			sellQuoteOrder.setTradeFee(new BigDecimal(QuoteOrderConstant.QUOTE_TRADE_FEE));
			sellQuoteOrder.setUserId(sellerUserId);
			long id = this.quoteOrderDao.saveQuoteOrder(sellQuoteOrder);
			//冻结对应的币种数量
			boolean asset = this.userAssetService.freezeUser_Asset(sellerUserId+"", coinCode, amountCoin);
		if(id > 0 && asset){
			return true;
			}else{
			//TODO 优化
			return false;
		}
		}else if(!StringUtils.isEmpty(buyserUserId) && quoteId > 0 ){
			//指定买家卖出
			//买家不能买自己的卖单
			logger.info("指定买家卖出报价单，报价单id,买入用户id,卖出用户id,数量,参数"+Arrays.asList(new Object[]{quoteId,buyserUserId,sellerUserId,amountCoin}));
			//
			QuoteOrder quoteOrder = this.quoteOrderDao.getQuoteOrderInfo(quoteId);
		    //有指定买家买入
		    UserSafeInfo seller = userSafeInfoProxy.verificationSafeInfo(sellerUserId);
		   if(seller == null ){
			throw new BusinessException("QO014", "seller is not exist ", null);
		   }
		   if(quoteOrder.getUserId() != Integer.valueOf(buyserUserId)){
			   throw new BusinessException("QO016", "buyser info is wrong", null);
		   }
		   //买家不能买自己的卖单
		   if(quoteOrder.getUserId() == sellerUserId){
			   throw new BusinessException("QO024", "buyser seller is same ", null); 
		   }
		   BigDecimal  remainAmount = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount());
		   //剩余的币数小于订单数
		   int result = amountCoin.compareTo(remainAmount);
		   if( result == 1){
			   throw new BusinessException("QO021", "order balance is not enought", null);
		   }
		   //如果买入额和卖出额相同就为全部吃货 需要删除对应的报价单产生交易记录
		   if(result == 0){
			   //TODO 全部买入 设置tradeSatus 为最后一笔交易 
			   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_LAST);
			   //TODO 剩余数量是否足够
			   quoteOrder.setDealAmount(quoteOrder.getDealAmount().add(amountCoin));//TODO 已交易数量  交易后数量必须大于最小交易数量否则资产回归
		   }else if(result == -1){
		      //部分卖出
			   quoteOrder.setDealAmount(quoteOrder.getDealAmount().add(amountCoin));
			   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_DOING);
		     //TODO 剩余额 100 最小交易额 10 买入 99
			   BigDecimal remainA = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount());//剩余币数量
			   BigDecimal minALO = new BigDecimal(quoteOrder.getALOtransaction());//最小交易金额
			 //TODO 出现质数的处理办法   全局统一是用 TODO ****
			   BigDecimal unit = minALO.divide(quoteOrder.getPriceCNY(),QuoteOrderConstant.QUOTE_CNY_ACCURAY,BigDecimal.ROUND_HALF_EVEN);//TODO 封装
			   //判断剩余数量是否小于最小交易数
			   if(remainA.compareTo(unit) == -1){
				   //余额小于最小交易
				   //1、余额进行退回 2、添加交易记录 3、修改交易状态为2
				   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_LAST);
				   //余额回退
				   isrefund = true;
				   refund = remainA.toString();
			   }else{
				   //余额数可以进行再次交易
				   //1、添加交易记录   2、修改交易状态为1
				   quoteOrder.setTradeCode(QuoteOrderConstant.QUOTE_TRADESTATUS_DOING);
			   }
		   }
		// 添加交易记录
		//判断报价单余额是否小于最小交易额  币数退回
		this.quoteOrderDao.updateQuoteOrder(quoteOrder);
		TradeLog initTradeLog = tradeLogService.getInitTradeLog();
		initTradeLog.setBuyserUid(Integer.valueOf(buyserUserId));
		initTradeLog.setCoinAmount(amountCoin);
		initTradeLog.setCoinCode(coinCode);
		initTradeLog.setCoinName(coinName);
		initTradeLog.setQuoteId(quoteId);
		initTradeLog.setSellerUid(sellerUserId);
		initTradeLog.setTradeType(TradeLogConstants.TRADE_TYPE_SELL);
		initTradeLog.setUnitPrice(new BigDecimal(priceCNY));
		initTradeLog.setTotalPrice(totalPrice);
		initTradeLog.setPayType(payType);
		initTradeLog.setPoundageBTC(new BigDecimal(QuoteOrderConstant.QUOTE_TRADE_FEE));
		tradeLogService.saveTradeLog(initTradeLog);
		//退回剩余币数
		if(isrefund && refund != null){
			logger.info("报价单余额小于最小交易数量进行退回，报价单号，剩余币数,退回卖家id："+new Object[]{quoteId,refund,sellerUserId});
			//TODO 剩余数量小于最小交易进行报价单如何处理 直接删除报价单
		}
		logger.info("报价订单生成，参数"+quoteOrder.toString());
		return true;
		}
		return false;
	}


	@Transactional
	@Override
	public boolean cancelQuoteOrder(long quoteId, int quoteStatus,long userId) throws BusinessException {
		logger.info("撤销报价订单方法调用，参数:"+Arrays.asList(new Object[]{quoteId,quoteStatus,userId}));
		boolean flag = false;
		QuoteOrder order = this.quoteOrderDao.getQuoteOrderInfo(quoteId);
		if(order == null){
			throw new BusinessException("QO003", "quoteOrder is not exist!", null);
		}
		if(order != null && order.getUserId()== userId){
			//获取报价状态
			int status = order.getQuoteStatus();
			if(quoteStatus != status){
				throw new BusinessException("QO004", "quoteOrder being edited", null);
			}
			switch(status){
			case QuoteOrderConstant.QUOTE_STATUS_NODEAL:
				//将订单的解冻资产传给资产进行解冻
				logger.info("没有进行交易，撤单退回数量，退回币种： "+ new Object[]{order.getAmountCoin(),order.getCoinCode()});
				//将资产解冻  负值表示解冻   正值表示冻结
				flag = this.userAssetService.freezeUser_Asset(userId+"", order.getCoinCode(),new BigDecimal("-"+order.getAmountCoin().doubleValue()));
				break;
			case QuoteOrderConstant.QUOTE_STATUS_DEALING:
				// 成交中的订单不做处理 剩余的订单值退回至资产 部分解冻
				logger.info("部分交易中，值退回未产生交易的部分，撤单退回数量，退回币种"+ new Object[]{order.getAmountCoin(),order.getCoinCode()});
				flag = this.userAssetService.freezeUser_Asset(userId+"",order.getCoinCode(), order.getDealAmount().subtract(order.getAmountCoin()));//TODO 精确度
				break;
			case QuoteOrderConstant.QUOTE_STATUS_PART_DEAL:
				//TODO 成交中的订单不做处理 剩余的订单值退回至资产 部分解冻
				logger.info("部分交易完成，值退回未产生交易的部分，撤单退回数量，退回币种"+ new Object[]{order.getAmountCoin(),order.getCoinCode()});
				flag = this.userAssetService.freezeUser_Asset(userId+"",order.getCoinCode(), order.getDealAmount().subtract(order.getAmountCoin()));
				break;
			default:
				flag = false;
					break;
			}
			//解冻成功进行删除订单
			if(flag){
			this.quoteOrderDao.deleteQuoteOrder(order.getId());
			}
			return flag;
		}
		return flag;
	}


	//查询字段 all :全部   buy： 买入  sell：卖出
	@Override
	public PageListRes<QuoteOrderVO> getQuoteOrderList(int userId, String coinCode, String queryStr, Integer pageNumber, Integer pageSize) {
		 List<QuoteOrderVO> orderVoList = new ArrayList<QuoteOrderVO>();
		int querytype = 3;
		if("buy".equals(queryStr)){
			querytype = 0;
		}
		if("sell".equals(queryStr)){
			querytype = 1;
		}
		int count = this.quoteOrderDao.getQuoteOrderCount(userId, coinCode, querytype);
		PageListRes<QuoteOrderVO> pageResp = PageListRes.createInstance(pageNumber, pageSize,count);
		List<QuoteOrder> list = this.quoteOrderDao.getQuoteOrderList(userId, coinCode,querytype, pageResp.getFirst()-1, pageResp.getPageSize());
		
		for (QuoteOrder quoteOrder : list) {
			QuoteOrderVO orderVo =new QuoteOrderVO(quoteOrder);
			orderVo.setTradeStatus(getQuoteOrderStatus(quoteOrder.getId()));
			orderVo.setTransactionProgress(quoteOrder.getDealAmount().divide(quoteOrder.getAmountCoin(),2,BigDecimal.ROUND_HALF_EVEN).multiply(new BigDecimal("100")).doubleValue());
			orderVoList.add(orderVo);
		}
		pageResp.setList(orderVoList);
		return pageResp;
	}


	/**
	 * 获取报价单状态
	 * @description ：0：未成交  1：部分成交中  2：部分成交
	 * @param quoteId 报价单id
	 * @return 0：未成交  1：部分成交中  2：部分成交
	 */
	private int getQuoteOrderStatus(long quoteId) {
		int status = QuoteOrderConstant.QUOTE_STATUS_NODEAL;
		/* 状态,0：未付款 1：已付款 2：已完成 3：买家已取消 4：超时取消 */
		List<Integer> list = new ArrayList<Integer>();
		List<TradeLog> tradeLogListByQuoteId = tradeLogProxy.getTradeLogListByQuoteId(quoteId);
		for (TradeLog tradeLog : tradeLogListByQuoteId) {
			list.add(tradeLog.getPayStatus());
		}
		if(list.contains(TradeLogConstants.PAY_STATUS_NOT_PAY)||list.contains(TradeLogConstants.PAY_STATUS_HAVE_PAY)){
			status = QuoteOrderConstant.QUOTE_STATUS_PART_DEAL;
		}
		if(list.contains(TradeLogConstants.PAY_STATUS_DONE)){
			status = QuoteOrderConstant.QUOTE_STATUS_DEALING;
		}
		return status;
	}


	@Transactional
	@Override
	public Map<String, Object> getGrailData(String coinCode,Integer dataSize) {
		Map<String ,Object> resultMap = new HashMap<String ,Object>();
		//1、查看币种是否存在 
		
		//TODO 查看币种是否存在
		
		//获取买盘信息
		List <QuoteOrder> selllist = this.quoteOrderDao.getGrailData(coinCode,QuoteOrderConstant.DIRECTION_SELL,dataSize);
		//封装返回数据卖家
		resultMap.put("buyorders", getMapFromList(selllist));
		//获取卖盘信息
		List<QuoteOrder> buylist = this.quoteOrderDao.getGrailData(coinCode, QuoteOrderConstant.DIRECTION_BUY,dataSize);
		//封装卖家信息
		resultMap.put("sellorders", getMapFromList(buylist));
		return resultMap;
	}
	/**
	 * 检查价格是否在指定范围内   
	 * @author 赵世栋
	 * @param orderPrice  报价单价格
	 * @param coinCode    币种码
	 * @param tradeType   交易类型   0：买入  1：卖出
	 * @description 价格不能超过指数价的120% 不能低于指数价的80%
	 * @return true ：合法   false 不合法
	 */
	protected boolean checkPriceIsValid(double orderPrice,String coinCode,int tradeType){
		BigDecimal orderP =  new BigDecimal(orderPrice+"");
		//TODO 获取最新指数价， 获取广道提供相关接口 
		// 最新指数价从后台获取 严防恶意攻击 TODO 
		double lastPrice=1000;
		BigDecimal lastP = new BigDecimal(lastPrice+"");
		if(lastP.compareTo(orderP) == 0){
			return true;
		}
		double flag = orderP.divide(lastP,QuoteOrderConstant.QUOTE_CNY_ACCURAY,BigDecimal.ROUND_HALF_EVEN).doubleValue();
		if(tradeType == 0){
			if(flag > 1.2){
				return false;
			}
			return true;
		}
		if(tradeType == 1){
			if(flag < 0.8){
				return false ;
			}
			return true;
		}
		return false;
	}


	@Override
	public boolean updateAutoSettingQuoteOrder()throws BusinessException{
		//获取所有设置了自动增益的订单
		List<QuoteOrder> list = this.quoteOrderDao.getQuoteIdsWithAutoSettig();
		if(list.size()<1){
			throw new BusinessException("QO006", "autoset order is zero", null);
		}
		logger.info("设置自动增益的报价订单信息："+list.size());
		//修改报价订单对应的剩余额个售价即可
		for (QuoteOrder quoteOrder : list) {
			 BigDecimal value = new BigDecimal(quoteOrder.getSetValue());
			 BigDecimal indexprice =new BigDecimal("1000");//TODO 指数价需要道广提供接口
			 BigDecimal priceCNY = indexprice.multiply(value).setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_EVEN);
			 BigDecimal  remain = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount()).setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_EVEN);
			quoteOrder.setPriceCNY(priceCNY);//TODO 指数价*增益数 四舍五入
			quoteOrder.setRemainPrice(remain.multiply(priceCNY).setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_UP));
			logger.info("自动增益报价单开始执行:"+Arrays.asList(new Object[]{quoteOrder.getId(),value,indexprice,priceCNY,remain}));
			this.quoteOrderDao.updateQuoteOrder(quoteOrder);
		}
		//TODO 设置自动增益后的报价单在不同的交易状态时价格该怎么呈现
		return true;
	}
	/**
	 * 解析报价单返回结果
	 * @param 报价单列表
	 * @return
	 */
	private List<Map<String,Object>> getMapFromList(List <QuoteOrder> list){
		boolean flag =false;
		List<Map<String,Object>> result= new ArrayList<Map<String,Object>>();
		for (QuoteOrder quoteOrder : list) {
			Map<String,Object> map =new HashMap<String,Object>();
			UserTradeRecord tradeRecord = this.userTradeRecordDao.getUserTradeRecordeInfo(quoteOrder.getUserId());
			 UserSafeInfo userSafeInfo = this.userSafeInfoProxy.verificationSafeInfo(quoteOrder.getUserId());
			 String nickName = this.userBaseInfoProxy.getNickNameByUserId(quoteOrder.getUserId());
			 flag = userSafeInfo.getAuthenStatus()== 3 ? true : false; 
			if(tradeRecord == null){
				map.put("tradeFinishCount", 0);
				map.put("tradeFinishRate", "0.0");
			}else{
				map.put("tradeFinishCount", tradeRecord.getTradeFinishCount());
				map.put("tradeFinishRate", this.getTradeFinishRate(tradeRecord.getTradeFinishCount(), tradeRecord.getFailTradeCount()));
			}
			BigDecimal remain = quoteOrder.getAmountCoin().subtract(quoteOrder.getDealAmount());
			map.put("priceCNY", quoteOrder.getPriceCNY());
			map.put("remainCoin", remain);//2018-01-18改为剩余数量
			map.put("ALOtranscation", quoteOrder.getALOtransaction());
			map.put("remainPrice", quoteOrder.getPriceCNY().multiply(remain).setScale(QuoteOrderConstant.QUOTE_CNY_ACCURAY, BigDecimal.ROUND_HALF_EVEN));//查询计算
			map.put("consigner", nickName);
			map.put("payType", quoteOrder.getPayType());
			map.put("userId", quoteOrder.getUserId());
			map.put("isAuth", flag);
			map.put("coinCode", quoteOrder.getCoinCode());
			map.put("quoteId", quoteOrder.getId());
			result.add(map);
		}
		return result;
	}
	/**
	 * 获取交易完成率
	 * @param success 交易成功次数
	 * @param fail    交易失败次数
	 * @return
	 */
	private String getTradeFinishRate(Integer success,Integer failure){
		if(success == null ||success == 0){
			return "0.0";
		}
		if(failure == null){
			return "100.0";
		}
		BigDecimal succ = new BigDecimal(String.valueOf(success));
		BigDecimal fail = new BigDecimal(String.valueOf(failure));
		BigDecimal sum = succ.add(fail);
		BigDecimal setScale = succ.divide(sum,3,BigDecimal.ROUND_HALF_UP);
		return setScale.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
	};
	/**
	 * 验证资产是否符合
	 * @param coincode 币种码
	 * @param userId   用户Id
	 * @return  true :符合  false:不符合
	 * @throws BusinessException
	 */
	boolean checkAssetIsEought(String coincode,int userId)throws BusinessException{
		boolean flag = false;
		BigDecimal newTradeCNY = tradeLogProxy.getNewTradeCNY(coincode);
		if(newTradeCNY == null||newTradeCNY == BigDecimal.ZERO){
			throw new BusinessException("QO0014", "lastest price is null", null);
		}
		BigDecimal coinAmouts = this.userAssetService.getCoinAmouts(userId,coincode);//TODO  获取剩余可用的数量
		BigDecimal mincount = newTradeCNY.divide(new BigDecimal(QuoteOrderConstant.QUOTE_INIT_COUNT));
		if(coinAmouts.compareTo(mincount)==1){
			flag =true;
		}
		return flag;
		
	}
	/**
	 * 检查下单条件
	 * @param coinCode 币种码
	 * @param userId   用户Id
	 * @throws BusinessException
	 */
	String checkQuoteOrderCondition(String coinCode,int userId)throws BusinessException{
		String result = null;
		//1、对应的币种是否在流通状态
		CoinTradeBusiType coinTradeBus = this.coinTradeBusiTypeDao.getCoinTradeBusiStatus(coinCode);
		if(coinTradeBus == null){
				throw new BusinessException("QO018", "coin need examine ", null);
		}
		if( coinTradeBus.getTradeStatus()!= 1){
			throw new BusinessException("QO002", "coin is not circ.ulation", null);
		}
		//2、账户是否冻结   0:活动 1：冻结  2：提币冻结 
		UserSafeInfo userInfo = userSafeInfoProxy.verificationSafeInfo(userId);
		if(userInfo == null){
			throw new BusinessException("QO009", "user is not exist", null);
		}
		if(userInfo.getFreezeStatus() == 1){
			throw new BusinessException("QO010", "account is freezen", null);
		}
		
		//3、判断买入方设置实名认证   3：已认证
		if(userInfo.getAuthenStatus() != 3){
			throw new BusinessException("QO011", "no certification", null);
		}
		//4、设置资产密码
		if(StringUtils.isEmpty(userInfo.getFundPassword())){
			throw new BusinessException("QO012", "set fundpassword", null);
		}
		//5、判断是否绑定手机 0:未绑定
		if(userInfo.getBindPhone() == 0){
			throw new BusinessException("QO013", "binding phone", null);
		}
		//6、判断昵称是否设置 是否绑定 TODO 
		if(userBaseInfoProxy.getNickNameByUserId(userId) == null){
			throw new BusinessException("QO020", "nickname is not to set", null);
		}
//		//7、是否有剩余未支付的报价单  包含 0：未付款 就是有没有支付的
//		List<TradeLog> tradeLogListByUserId = tradeLogProxyImpl.getTradeLogListByUserId(userId);
//		List<Integer> list =new ArrayList<Integer>();
//		for (TradeLog tradeLog : tradeLogListByUserId) {
//			list.add(tradeLog.getPayStatus());
//		}
//		if(list.contains(0)){
//			throw new BusinessException("QO019", "please finish your order", null);
//		}
		//8、在挂单情况下进行判断账户余额是否大于对应币种的1000
		boolean isEought = checkAssetIsEought(coinCode,userId);
		if(!isEought){
			throw new BusinessException("QO015", "asset is not enought", null);
		}
		result = coinTradeBus.getCoinName();
		return result;
	}
}
